
// import oimo.m.Mat3;
// import oimo.m.Vec3;
// import oimo.m.M;
// import oimo.common.Transform;
// import oimo.common.Vec3;
// import oimo.collision.raycast.*;

import { Mat3 } from "../../common/Mat3";
import { Transform } from "../../common/Transform";
import { Vec3 } from "../../common/Vec3";
import { RayCastHit } from "./RayCastHit";
import { Aabb } from "./Aabb";

/**
 * Abstract collision geometry.
 */

export class Geometry {
	_type: number;
	_volume: number;
	_inertiaCoeff: Mat3 = new Mat3(); // I / mass


	constructor(type: number) {
		this._type = type;
		this._volume = 0;
	}

	// --- internal ---

	public _updateMass(): void {
	}

	public _computeAabb(aabb: Aabb, tf: Transform): void {
	}

	public _rayCastLocal(begin: Vec3, end: Vec3, hit: RayCastHit): boolean {
		return false;
	}

	// --- public ---

	/**
	 * Returns the type of the collision geometry.
	 *
	 * See `GeometryType` for details.
	 */
	public getType(): number {
		return this._type;
	}

	/**
	 * Returns the volume of the collision geometry.
	 */
	public getVolume(): number {
		return this._volume;
	}

	/**
	 * Performs ray casting. Returns `true` and sets the result information to `hit` if
	 * the line segment from `begin` to `end` and the geometry transformed by `transform`
	 * intersect. Returns `false` if the line segment and the geometry do not intersect.
	 */
	public rayCast(begin: Vec3, end: Vec3, transform: Transform, hit: RayCastHit): boolean {
		let beginLocal = begin.clone();
		let endLocal = end.clone();
		beginLocal.subEq(transform._position);
		endLocal.subEq(transform._position);
		beginLocal.mulMat3Eq(transform._rotation);
		endLocal.mulMat3Eq(transform._rotation);
		if (this._rayCastLocal(beginLocal, endLocal, hit)) {
			let localPos = hit.position;
			let localNormal = hit.normal;
			// local -> global
			localPos.mulMat3Eq(transform._rotation);
			localNormal.mulMat3Eq(transform._rotation);
			localPos.addEq(transform._position);
			return true;
		}
		return false;
	}

}
